package com.cennavi.minemap.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cennavi.minemap.bean.LayerBean;
import com.cennavi.minemap.bean.LayerPrefixBean;
import com.cennavi.minemap.bean.LayerPrefixTreeWithLayerBean;
//import com.cennavi.minemap.bean.LayerBean;
import com.cennavi.minemap.bean.LayerWithPrefixBean;
import com.cennavi.minemap.bean.SoluBean;
import com.cennavi.minemap.bean.SoluLogBean;
import com.cennavi.minemap.bean.SoluWithPrefixLayerBean;
import com.cennavi.minemap.bean.SourceBean;
import com.cennavi.minemap.bean.SourceMergeBean;
import com.cennavi.minemap.bean.ThumbnailBean;
import com.cennavi.minemap.bean.UploadSoluBean;
import com.cennavi.minemap.dao.LayerDao;
import com.cennavi.minemap.dao.ReportDao;
import com.cennavi.minemap.dao.SoluDao;
import com.cennavi.minemap.dao.SourceDao;
import com.cennavi.minemap.dao.TokenDao;
import com.cennavi.minemap.util.Constants;
import com.cennavi.minemap.util.DateTimeUtil;
import com.cennavi.minemap.util.StringUtil;

@Service
@ComponentScan(basePackages = { "com.cennavi.minemap.dao" })
public class SoluService {
	@Autowired
	private SoluDao soluDao;

	@Autowired
	private LayerDao layerDao;

	@Autowired
	private SourceDao sourceDao;

	@Autowired
	private ReportDao reportDao;

	@Autowired
	private TokenDao tokenDao;

	public List<SoluBean> insert(SoluBean soluBean) {
		soluBean.setCreateTime(DateTimeUtil.getNow());
		soluBean.setLastUpdateTime(DateTimeUtil.getNow());
		soluBean.setStatus(0);
		soluBean.setIsTemplate(0);
		int id = soluDao.insert(soluBean);
		return Arrays.asList(soluDao.queryById(id));
	}

	public List<SoluBean> update(SoluBean soluBean) {
		soluBean.setLastUpdateTime(DateTimeUtil.getNow());
		int status = soluDao.update(soluBean);
		if (status < 0) {
			return null;
		} else {
			return Arrays.asList(soluDao.queryById(soluBean.getId()));
		}
	}

	@Transactional
	public int delete(int id) {
		int r1 = soluDao.delete(id);
		int r2 = layerDao.deleteBySoluId(id);
		int r3 = layerDao.deletePublishBySoluId(id);
		int r4 = tokenDao.deleteBySoluId(id);
		return r1 + r2 + r3 + r4;
	}

	// 只查解决方案不记录日志
	public List<SoluBean> queryById(int id) {
		SoluBean soluBean = soluDao.queryById(id);
		List<LayerWithPrefixBean> layerBeans = layerDao.queryBySoluId(id);
		soluBean.setLayers(layerBeans);
		return Arrays.asList(soluBean);
	}

	// 只查解决方案不记录日志
	public List<SoluBean> queryPublishById(int id) {
		SoluBean soluBean = soluDao.queryById(id);
		List<LayerWithPrefixBean> layerBeans = layerDao.queryPublishBySoluId(id);
		soluBean.setLayers(layerBeans);
		return Arrays.asList(soluBean);
	}

	// 只查解决方案不记录日志
	public List<SoluBean> queryByUrl(String url) {
		SoluBean soluBean = soluDao.queryByUrl(url);
		int id = soluBean.getId();
		/**
		 * 2017-03-16 查询发布后的表
		 */
		List<LayerWithPrefixBean> layerBeans = layerDao.queryPublishBySoluId(id);

		List<String> list = tokenDao.queryTokenSoluBySoluId(id);

		soluBean.setLayers(layerBeans);
		soluBean.setTokens(list);
		return Arrays.asList(soluBean);
	}
	
	public List<SoluWithPrefixLayerBean> queryWithPrefixLayerById(int id) {
		SoluBean soluBean = soluDao.queryById(id);
		List<LayerPrefixTreeWithLayerBean> basic = layerDao.queryLayerPerfixTreeWithLaByFather(null, id, 0, 1);
		List<LayerPrefixTreeWithLayerBean> special = layerDao.queryLayerPerfixTreeWithLaByFather(null, id, 0, 2);
		int userId = soluBean.getUserId();
		
		List<SourceBean> sources = sourceDao.queryUploadSourceByUserId(userId);
		
		List<LayerBean> layers = layerDao.queryUploadSourceByUserId(userId);
		
		List<LayerPrefixBean> layerPrefixs = layerDao.queryLayerPerfixTreeByType(3);
		
		SoluWithPrefixLayerBean soluWithPrefixLayerBean = new SoluWithPrefixLayerBean(soluBean);
		soluWithPrefixLayerBean.setBasic(basic);
		soluWithPrefixLayerBean.setSpecial(special);
		soluWithPrefixLayerBean.setUpload(sources, layers, layerPrefixs);
		return Arrays.asList(soluWithPrefixLayerBean);
	}

	public void saveSoluLog(int id, String ip) {
		SoluBean soluBean = soluDao.queryById(id);
		SoluLogBean soluLogBean = new SoluLogBean();
		soluLogBean.setUserId(soluBean.getUserId());
		soluLogBean.setSoluId(soluBean.getId());
		soluLogBean.setIsPublish(soluBean.getStatus());
		soluLogBean.setIp(ip);
		soluLogBean.setDateTime(DateTimeUtil.getNow());
		reportDao.insert(soluLogBean);
	}

	public List<SoluBean> saveSoluLogAndQuerySolu(String url, String ip) {
		SoluBean soluBean = soluDao.queryByUrl(url);
		SoluLogBean soluLogBean = new SoluLogBean();
		soluLogBean.setUserId(soluBean.getUserId());
		soluLogBean.setSoluId(soluBean.getId());
		soluLogBean.setIsPublish(soluBean.getStatus());
		soluLogBean.setIp(ip);
		soluLogBean.setDateTime(DateTimeUtil.getNow());
		reportDao.insert(soluLogBean);
		return Arrays.asList(soluBean);
	}

	public Map<String, Object> queryByIdForDownload(int soluId) {
		Map<String, Object> map = new HashMap<String, Object>();
		SoluBean soluBean = soluDao.queryById(soluId);
		List<LayerWithPrefixBean> layerBeans = layerDao.queryPublishBySoluId(soluId);
		if (layerBeans == null || layerBeans.size() == 0) {
			layerBeans = layerDao.queryBySoluId(soluId);
		}
		map.put("solu", soluBean);
		map.put("layers", layerBeans);
		return map;
	}

	public List<SoluBean> queryByUserId(int userId) {
		List<SoluBean> soluBeans = soluDao.queryByUserId(userId);
		for (SoluBean soluBean : soluBeans) {
			List<String> list = tokenDao.queryTokenSoluBySoluId(soluBean.getId());
			soluBean.setTokens(list);
		}
		return soluBeans;
	}

	public List<SoluBean> queryIdNameByUserId(int userId) {
		return soluDao.queryIdNameByUserId(userId);
	}

	public List<SoluBean> queryTemplate() {
		List<SoluBean> soluBeans = soluDao.queryTemplate();
		for (SoluBean soluBean : soluBeans) {
			List<String> list = tokenDao.queryTokenSoluBySoluId(soluBean.getId());
			soluBean.setTokens(list);
		}
		return soluBeans;
	}

	public List<SoluBean> queryByIdWithToken(int id) {
		SoluBean soluBean = soluDao.queryById(id);
		List<String> list = tokenDao.queryTokenSoluBySoluId(id);
		soluBean.setTokens(list);
		return Arrays.asList(soluBean);
	}

	public List<SoluBean> queryTemplate2() {
		List<SoluBean> soluBeans = soluDao.queryTemplate2();
		for (SoluBean soluBean : soluBeans) {
			List<String> list = tokenDao.queryTokenSoluBySoluId(soluBean.getId());
			soluBean.setTokens(list);
		}
		return soluBeans;
	}

	@Transactional
	public List<SoluBean> publish(int id) {
		SoluBean soluBean = new SoluBean();
		soluBean.setId(id);
		soluBean.setLastUpdateTime(DateTimeUtil.getNow());
		soluBean.setPublishTime(DateTimeUtil.getNow());
		soluBean.setUrl(StringUtil.uuid().replace("-", ""));
		// 发布后将内容拷贝到layer_publish表中 2016-03-16
		int status1 = soluDao.publish(soluBean);
		int status2 = layerDao.deletePublishBySoluId(soluBean.getId());
		int status3 = layerDao.copyToPublish(soluBean.getId());

		if (status1 + status2 + status3 < 0) {
			return null;
		} else {
			return Arrays.asList(soluDao.queryById(id));
		}
	}

	@Transactional
	public List<SoluBean> copy(int id, SoluBean inputBean) {
		try {
			SoluBean soluBean = soluDao.queryById(id);

			inputBean.setIcon(soluBean.getIcon());
			// inputBean.setDescribe(soluBean.getDescribe());
			inputBean.setCreateTime(DateTimeUtil.getNow());
			inputBean.setLastUpdateTime(DateTimeUtil.getNow());

			inputBean.setTemplate(soluBean.getTemplate());
			inputBean.setCenter(soluBean.getCenter());
			inputBean.setBearing(soluBean.getBearing());
			inputBean.setPitch(soluBean.getPitch());

			inputBean.setStatus(0);
			inputBean.setZoom(soluBean.getZoom());
			inputBean.setMinZoom(soluBean.getMinZoom());
			inputBean.setMaxZoom(soluBean.getMaxZoom());
			inputBean.setIsTemplate(0);
			inputBean.setConfig(soluBean.getConfig());

			List<LayerWithPrefixBean> layerBeans = null;

			int newSoluId = soluDao.insert(inputBean);
			// 为发布拷贝发布前的，以发布拷贝发布后的 2016-03-16
			if (soluBean.getUrl() == null) {
				layerBeans = layerDao.queryBySoluId(id);
			} else {
				layerBeans = layerDao.queryPublishBySoluId(id);
			}

			for (LayerWithPrefixBean layerBean : layerBeans) {
				String layerId = StringUtil.uuid().replace("-", ""); // add by
																		// zhangjin
																		// 重新申请ID
				layerBean.setId(layerId);
				layerBean.setSoluId(newSoluId);
				layerDao.insert(layerBean);
			}
			return Arrays.asList(soluDao.queryById(newSoluId));
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public JSONObject queryStyle(int soluId) {

		JSONObject json = new JSONObject();
		json.put("version", 8);
		json.put("sprite", "minemap://sprite/sprite");
		json.put("glyphs", "minemap://fonts/{fontstack}/{range}");

		JSONArray layers = new JSONArray();

		List<LayerWithPrefixBean> layerList = layerDao.queryBySoluId(soluId);
		Integer[] sourceIds = new Integer[layerList.size()];
		for (int i = 0; i < layerList.size(); i++) {
			LayerWithPrefixBean layerBean = layerList.get(i);
			sourceIds[i] = layerBean.getSourceId();
			JSONObject layer = JSONObject.parseObject(layerBean.getContent());

			JSONArray filter = layer.getJSONArray("filter");
			if (filter.size() == 0) {
				layer.remove("filter");
			}
			layer.put("id", layerBean.getId());
			layers.add(layer);
		}
		json.put("layers", layers);

		List<SourceBean> sourceList = sourceDao.queryById(sourceIds);

		JSONObject sources = new JSONObject();

		for (SourceBean sourceBean : sourceList) {
			String code = sourceBean.getCode();
			String type = sourceBean.getType();
			JSONObject source = JSONObject.parseObject(sourceBean.getContent());
			source.put("type", type);

			sources.put(code, source);
		}
		json.put("sources", sources);
		return json;
	}

	public JSONObject queryPublishStyle(int soluId) {

		JSONObject json = new JSONObject();
		json.put("version", 8);
		json.put("sprite", "minemap://sprite/sprite");
		json.put("glyphs", "minemap://fonts/{fontstack}/{range}");

		JSONArray layers = new JSONArray();

		List<LayerWithPrefixBean> layerList = layerDao.queryPublishBySoluId(soluId);
		// Integer[] sourceIds = new Integer[layerList.size()];

		// List<Integer> unMergedSourceIds = new ArrayList<Integer>();
		// List<Integer> mergedSourceIds = new ArrayList<Integer>();

		Map<String, List<Integer>> sourceIds = new HashMap<String, List<Integer>>();

		for (int i = 0; i < layerList.size(); i++) {
			LayerWithPrefixBean layerBean = layerList.get(i);
			SourceMergeBean sourceMergeBean = sourceDao.queryMergeBySourceid(layerBean.getSourceId());

			JSONObject layer = JSONObject.parseObject(layerBean.getContent());
			if (sourceMergeBean != null) {
				// 如果属于合并图层则将merge表的id覆盖source
				layer.put("source", sourceMergeBean.getId());
				if (sourceIds.get(sourceMergeBean.getId()) == null) {
					sourceIds.put(sourceMergeBean.getId(), new ArrayList<Integer>());
				}
				sourceIds.get(sourceMergeBean.getId()).add(sourceMergeBean.getSourceId());

			} else {
				if (sourceIds.get(Constants.UNMERGE_SOURCE) == null) {
					sourceIds.put(Constants.UNMERGE_SOURCE, new ArrayList<Integer>());
				}
				sourceIds.get(Constants.UNMERGE_SOURCE).add(layerBean.getSourceId());
			}
			JSONArray filter = layer.getJSONArray("filter");
			if (filter.size() == 0) {
				layer.remove("filter");
			}
			layer.put("id", layerBean.getId());
			layers.add(layer);
		}
		json.put("layers", layers);

		List<SourceBean> sourceList = sourceDao
				.queryById(sourceIds.get(Constants.UNMERGE_SOURCE).toArray(new Integer[] {}));
		sourceIds.remove(Constants.UNMERGE_SOURCE);

		JSONObject sources = new JSONObject();

		for (SourceBean sourceBean : sourceList) {
			String code = sourceBean.getCode();
			String type = sourceBean.getType();
			JSONObject source = JSONObject.parseObject(sourceBean.getContent());
			source.put("type", type);
			sources.put(code, source);
		}

		Iterator<Entry<String, List<Integer>>> it = sourceIds.entrySet().iterator();
		while (it.hasNext()) {
			JSONObject source = new JSONObject();
			Map.Entry<String, List<Integer>> m = it.next();
			String key = m.getKey();
			List<Integer> value = m.getValue();
			List<SourceBean> mergeSourceList = sourceDao.queryById(value.toArray(new Integer[] {}));

			String mergeSources = "";

			Map<String, String> sourceMap = new HashMap<String, String>();

			for (SourceBean bean : mergeSourceList) {
				if (sourceMap.get(bean.getCode()) == null) {
					mergeSources = mergeSources + bean.getCode() + ",";
				}
				sourceMap.put(bean.getCode(), "1");
			}
			mergeSources = mergeSources.substring(0, mergeSources.length() - 1);
			JSONArray tiles = new JSONArray();
			tiles.add("minemapdatam://" + mergeSources + "/{z}/{x}/{y}");
			source.put("tiles", tiles);
			source.put("type", "vector");
			sources.put(key, source);
		}

		json.put("sources", sources);
		return json;
	}

	public List<SoluBean> querySoluListByUploadId(Integer uploadId) {
		List<SoluBean> soluBeans = soluDao.querySoluListByUploadId(uploadId);
		for (SoluBean soluBean : soluBeans) {
			List<String> list = tokenDao.queryTokenSoluBySoluId(soluBean.getId());
			soluBean.setTokens(list);
		}
		return soluBeans;
	}

	@Transactional
	public int updateUploadSolu(UploadSoluBean uploadSoluBean) {
		soluDao.deleteUploadSolu(uploadSoluBean);
		return soluDao.insertUploadSolu(uploadSoluBean);
	}

	public int queryTokenSolu(String tokenId, int soluId) {
		return tokenDao.queryTokenSolu(tokenId, soluId);
	}
	
	public List<ThumbnailBean> insertThumbnail(final ThumbnailBean thumbnailBean) {
		soluDao.insertThumbnail(thumbnailBean);
		return soluDao.queryThumbnail(thumbnailBean.getSoluId());
	}
	
	public List<ThumbnailBean> updateThumbnail(final ThumbnailBean thumbnailBean) {
		soluDao.updateThumbnail(thumbnailBean);
		return soluDao.queryThumbnail(thumbnailBean.getSoluId());
	}
	
	public int deleteThumbnail(int soluId) {
		return soluDao.deleteThumbnail(soluId);
	}

	public List<ThumbnailBean> queryThumbnail(int soluId) {
		return soluDao.queryThumbnail(soluId);
	}
}
